﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using CTP.Exceptions;

namespace CTP.Utilty
{
    /// <summary>  
    /// <![CDATA[
    /// 功能：配置提供类，获取XML配置文件中的值
    ///     XML格式如下：
    ///     <config>
    ///         <ConnectAddress value="1234" />    ///    
    ///         <ConnectPort value="1234" />
    ///     </config>
    /// 创建：陈粤雄 20120429
    /// ]]>
    /// </summary>
    internal class Config
    {
        #region 字段
        /// <summary>
        /// 静态单例
        /// </summary>
        private static Config m_Instance;

        private const string CONFIG_FILE_NAME = "ctpconfig.xml";
        #endregion

        #region 属性
        /// <summary>
        /// 获取配置类的单例
        /// </summary>
        public static Config Instance { get { return m_Instance; } }

        /// <summary>
        /// 获取与上期连接地址
        /// </summary>
        public string ConnectAddress { get; private set; }
        /// <summary>
        /// 获取与上期连接端口
        /// </summary>
        public int ConnectPort { get; private set; }
        /// <summary>
        /// 获取与上期连接的超时时间
        /// </summary>
        public int ConnectTimeout { get; private set; }
        /// <summary>
        /// 获取与上期行情连接地址
        /// </summary>
        public string ConnectAddressQoute { get; private set; }
        /// <summary>
        /// 获取与上期行情连接端口
        /// </summary>
        public int ConnectPortQoute { get; private set; }
        /// <summary>
        /// 获取与上期行情连接的超时时间
        /// </summary>
        public int ConnectTimeoutQoute { get; private set; }
        /// <summary>
        /// 获取下单速度
        /// </summary>
        public int SendSpeed { get; private set; }
        /// <summary>
        /// 获取是否记录调试日志
        /// </summary>
        public bool IsLogDebug { get; private set; }
        /// <summary>
        /// 获取是否记录信息日志
        /// </summary>
        public bool IsLogInfo { get; private set; }
        /// <summary>
        /// 获取是否记录错误日志
        /// </summary>
        public bool IsLogError { get; private set; }
        /// <summary>
        /// 获取调试日志保存目录
        /// </summary>
        public string LogDir { get; private set; }
        /// <summary>
        /// 日志文件最大大小
        /// </summary>
        public int LogRollFileSize { get; private set; }
        #endregion

        #region 构造
        static Config()
        {
            m_Instance = new Config();
        }

        private Config()
        {
            try
            {
                load();
            }
            catch (Exception ex)
            {
                Logger.Instance.WriteError(ex.Message);
            }
        }
        #endregion

        #region 方法
        /// <summary>
        /// 加载文件配置
        /// </summary>
        private void load()
        {            
            string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, CONFIG_FILE_NAME);
            if (!File.Exists(path))
                throw new Exceptions.CommonException("找不到配置文件：" + path);

            // 加载保存配置的文档
            XmlDocument doc = new XmlDocument();
            doc.Load(path);

            // 加载各个配置项
            ConnectAddress = getConfigValue<string>(doc, "ConnectAddress");
            ConnectPort = getConfigValue<int>(doc, "ConnectPort");
            ConnectTimeout = getConfigValue<int>(doc, "ConnectTimeout");
            ConnectAddressQoute = getConfigValue<string>(doc, "ConnectAddressQoute");
            ConnectPortQoute = getConfigValue<int>(doc, "ConnectPortQoute");
            ConnectTimeoutQoute = getConfigValue<int>(doc, "ConnectTimeoutQoute");
            SendSpeed = getConfigValue<int>(doc, "SendSpeed");
            IsLogDebug = getConfigValue<bool>(doc, "IsLogDebug");
            IsLogInfo = getConfigValue<bool>(doc, "IsLogInfo");
            IsLogError = getConfigValue<bool>(doc, "IsLogError");
            LogDir = getConfigValue<string>(doc, "LogDir");
            LogRollFileSize = getConfigValue<int>(doc, "LogRollFileSize");

            // 加载完成后检查配置
            checkConfig();
        }

        /// <summary>
        /// 获取配置项
        /// </summary>
        /// <param name="doc"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        private T getConfigValue<T>(XmlDocument doc, string key)
        {
            XmlNode node = doc.SelectSingleNode("/config/" + key);
            if (node == null)
                throw new Exceptions.CommonException("找不到配置项：" + key);
            else if (node.Attributes["value"] == null)
                throw new Exceptions.CommonException("配置项格式错误，" + key + "配置项找不到value标签");

            string value = node.Attributes["value"].Value;
            if (typeof(T) == typeof(string))
            {
                return (T)(object)value;
            }
            else if (typeof(T) == typeof(int))
            {
                int result;
                if (!int.TryParse(value, out result))
                    throw new CommonException("无效的配置项，值必须为整数，Key=" + key + ",value=" + value);

                return (T)(object)result;
            }
            else if (typeof(T) == typeof(bool))
            {
                int result;
                if (!int.TryParse(value, out result))
                    throw new CommonException("无效的配置项，值必须为整数，Key=" + key + ",value=" + value);

                bool boolResult = result > 0;
                return (T)(object)boolResult;
            }
            else
            {
                throw new CommonException("不支持配置类型，Key=" + key + ",Type=" + typeof(T));
            }
        }

        /// <summary>
        /// 检查配置
        /// </summary>
        private void checkConfig()
        {
            // 检查日志文件路径
            string path = "";
            if (Directory.Exists(LogDir))
            {
                path = LogDir;
            }
            else
            {
                LogDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, LogDir);
                if (!Directory.Exists(LogDir))
                {
                    try
                    {
                        Directory.CreateDirectory(LogDir);
                    }
                    catch (Exception ex)
                    {
                        throw new CommonException(string.Format("日志目录不存在，且无法创建日志目录:{0}，原因：{1}", LogDir, ex.Message));
                    }
                }
            }
        }

        #endregion
    }
}
